<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>读取本地文件</title>
    <style>
        .editor {
            display: flex;
        }

        .editor .menu {
            background-color: #303030;
        }

        .editor .menu #file-tree {
            width: 250px;
            padding: 10px;
            border-right: 1px solid #ccc;
            overflow: auto;
            height: 100vh;
        }

        .editor .menu #file-tree ul {
            list-style-type: none;
            padding: 0;
        }

        .editor .menu #file-tree li {
            cursor: pointer;
        }

        .editor .content {
            flex: 1;
            background-color: #303030;
        }
    </style>
    <link rel="stylesheet" href="highlightjs/styles/dark.min.css">
    <script src="highlightjs/highlight.min.js"></script>
</head>

<body>
    <div class="editor">
        <div class="menu">
            <button>打开文件夹</button>
            <div id="file-tree"></div>
        </div>
        <div class="content">
            <pre><code id="editor"></code></pre>
        </div>
    </div>

    <script>
        const btn = document.querySelector('button')
        const code = document.querySelector('code')
        btn.onclick = async function () {
            try {
                const handler = await window.showDirectoryPicker()
                const root = await processHandle(handler)
                buildFileTree([root], document.querySelector('#file-tree'))
            } catch (error) {
                alert('用户未授权')
            }
        }

        async function processHandle(handle) {
            if (handle.kind == 'file') {
                return handle
            }

            handle.children = []
            // iter 异步迭代器
            const iter = await handle.entries()

            for await (const info of iter) {
                const subHandle = await processHandle(info[1])
                handle.children.push(subHandle)
            }
            return handle
        }

        async function readFileContent(handle) {
            const file = await handle.getFile()
            const reader = new FileReader()
            reader.onload = (e) => {
                code.innerText = e.target.result
                hljs.highlightBlock(code)
            }
            reader.readAsText(file, 'utf-8')
        }

        function buildFileTree(files, parent) {

            if (!files || files.length === 0) return;

            const ul = document.createElement('ul');
            files.forEach(file => {
                const li = document.createElement('li');
                const span = document.createElement('span');
                span.textContent = file.name;
                span.classList.add('file-item');
                span.onclick = file.children ? toggleFolder : () => { readFileContent(file) };

                li.appendChild(span);

                if (file.children) {
                    buildFileTree(file.children, li);
                }

                ul.appendChild(li);
            });

            parent.appendChild(ul);
        }

        function toggleFolder(event) {
            const ul = event.target.nextElementSibling;
            if (ul) {
                ul.style.display = ul.style.display === 'none' ? 'block' : 'none';
            }
        }

    </script>
</body>

</html>